package com.example.netty.common.server;

import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.SocketAddress;

/**
 * <p></p>
 *
 * @author xin
 * @version 2023/11/2 16:23
 **/
public class ServerHeartBeatServerHandler extends ChannelInboundHandlerAdapter {
    private static final Logger logger = LoggerFactory.getLogger(ServerHeartBeatServerHandler.class);
    private static final int MIN_LOSS_CONNECT_COUNT = 12;
    private int lossConnectCount = 0;

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        logger.debug("已经5秒未收到客户端的消息了！");
        if (evt instanceof IdleStateEvent) {
            IdleStateEvent event = (IdleStateEvent) evt;
            if (event.state() == IdleState.READER_IDLE) {
                lossConnectCount++;
                if (lossConnectCount > MIN_LOSS_CONNECT_COUNT) {
                    logger.debug("这个不活跃通道！");
                    // 如果有需要可以关闭不活跃的通道
                    final SocketAddress socketAddress = ctx.channel().remoteAddress();
                    ctx.channel().close().addListener((ChannelFutureListener) future -> {
                        if (future.isSuccess()) {
                            logger.info("close idle connect:" + socketAddress + " for " + event.state() + " done");
                        } else {
                            logger.info("close idle connect:" + socketAddress + " for " + event.state() + " fail");
                        }
                    });
                }
            }
        } else {
            super.userEventTriggered(ctx, evt);
        }
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        lossConnectCount = 0;
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        ctx.close();
    }
}
